/*
 * ringbuffer.c
 *
 *  Created on: 2016-11-3
 *      Author: chenshisheng
 */


#include "ringbuffer.h"



/** 初始化环形队列
 *
 * @param cb 环形队列指针
 * @param buf 队列内容缓存
 * @param size 队内内容大小
 * @note  队内内容大小 必须为2的n次方
 */
void RingBuffer_Init(rbuf_t *cb, void *buf, unsigned int size)
{
	cb->size = size;
	cb->mask = 2 * cb->size - 1;
	cb->start = 0;
	cb->end = 0;
	cb->elems  = buf;
	cb->flags = 0;
}

void RingBuffer_SetFlags(rbuf_t *cb, unsigned int flags)
{
    cb->flags = flags;
}

#define _IS_FULL(cb) (cb->end == (cb->start ^ cb->size))
#define _IS_EMPTY(cb) (cb->end == cb->start)
#define _INCR(cb, p) ((p + 1) & cb->mask)

int8_t RingBuffer_IsFull(rbuf_t *cb)
{
   return _IS_FULL(cb);
}

int8_t RingBuffer_IsEmpyt(rbuf_t *cb)
{
    return _IS_EMPTY(cb);
}

int8_t RingBuffer_Write(rbuf_t *cb, void *e)
{
	int8_t rel = 0;
	elem_t *elem = e;

	if(_IS_FULL(cb) && !(cb->flags & RINGBUFFER_FLAG_OVERWRITE))
	{
	    return -1;
	}

	cb->elems[cb->end & (cb->size - 1)] = *elem;

	 /* full, overwrite moves start pointer */
	if(_IS_FULL(cb))
	{
		cb->start = _INCR(cb, cb->start);
		rel = -1;
	}

	cb->end = _INCR(cb, cb->end);

	return rel;
}

int8_t RingBuffer_Read(rbuf_t *cb, void *e)
{
	elem_t *elem = e;

	if(_IS_EMPTY(cb))
	{
		return -1;
	}
	else
	{
		*elem = cb->elems[cb->start & (cb->size - 1)];
		cb->start = _INCR(cb, cb->start);

		return 0;
	}
}

void RingBuffer_Clear(rbuf_t *cb)
{
    cb->end = 0;
    cb->start = 0;
}
